﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using System.Xml;

namespace CodeArt.SharePoint.CamlQuery
{
    /// <summary>
    /// 用户组类型字段查询
    /// </summary>
    public class MembershipQueryField : TypedQueryField<int>
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name">internal name of field</param>
        public MembershipQueryField(string name) : base(name)  
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name">internal or display name of field</param>
        /// <param name="isInternalName">if the first parameter is a internal name</param>
        public MembershipQueryField(string name, bool isInternalName)
            : base(name, isInternalName)
        {
        }
        /// <summary>
        /// 包含当前用户所属的组 
        /// </summary>
        /// <returns>表达式</returns>
        public CamlExpression ContainsCurrentUserGroup()
        {
            return new MembershipCurrentUserGroupsExpression(this.FieldName, this.IsInternalName);
        }
        /// <summary>
        /// 包含当前用户(直接有用户或包含用户组)
        /// </summary>
        /// <returns></returns>
        public CamlExpression ContainsCurrentUser()
        {
            TypedQueryField<QuerySchema.UserID> userField = new TypedQueryField<QuerySchema.UserID>(this.FieldName, this.IsInternalName);
            return (userField == new QuerySchema.UserID()) || this.ContainsCurrentUserGroup();
        }

        /// <summary>
        /// 字段保存的用户属于指定的组
        /// </summary>
        /// <param name="grpId">组ID</param>
        /// <returns></returns>
        public CamlExpression UserInGroup(int grpId)
        {
            return new MembershipGroupExpression(this.FieldName, this.IsInternalName, grpId);
        }

        protected override CamlExpression CreateExpression(string op, object value)
        {
            SingleCamlExpression q = new SingleCamlExpression(this.FieldName, op, value, typeof(SPUser), this.IsInternalName);
            return q;
        }      
    }

    //<Membership Type="CurrentUserGroups">
    //  <FieldRef Name="AssignedTo" />
    //</Membership>
    class MembershipCurrentUserGroupsExpression : CamlExpression
    {
        public MembershipCurrentUserGroupsExpression(string field, bool isInternalName)
        {
            FieldName = field;
            IsInternalName = isInternalName;
        }

        public readonly string FieldName;

        public readonly bool IsInternalName;

        public override void ToCaml(ICamlBuildProvider provider, System.Xml.XmlNode parentNode)
        {
            XmlElement node = parentNode.OwnerDocument.CreateElement("Membership");
            parentNode.AppendChild(node);

            base.ApppendAttribute(node, "Type", "CurrentUserGroups");
       
            XmlNode fieldNode = parentNode.OwnerDocument.CreateElement("FieldRef");
            node.AppendChild(fieldNode);

            base.ApppendAttribute(fieldNode, "Name",
                base.GetFieldInternalName(provider, this.FieldName, this.IsInternalName));
        }        
    }

//<Membership Type=””SPGroup”” ID=”7”>
//<FieldRef Name=””AssignedTo””/>
//</Membership>
    class MembershipGroupExpression : CamlExpression
    {
        private int grpId;
        public MembershipGroupExpression(string field, bool isInternalName, int grpId)
        {
            FieldName = field;
            IsInternalName = isInternalName;
            this.grpId = grpId;
        }

        public readonly string FieldName;

        public readonly bool IsInternalName;

        public override void ToCaml(ICamlBuildProvider provider, System.Xml.XmlNode parentNode)
        {
            XmlElement node = parentNode.OwnerDocument.CreateElement("Membership");
            parentNode.AppendChild(node);

            base.ApppendAttribute(node, "Type","SPGroup");
            base.ApppendAttribute(node, "ID", this.grpId.ToString());          

            XmlNode fieldNode = parentNode.OwnerDocument.CreateElement("FieldRef");
            node.AppendChild(fieldNode);

            base.ApppendAttribute(fieldNode, "Name", 
                base.GetFieldInternalName(provider,this.FieldName,this.IsInternalName));
        }
    }
}
